package com.execjar.pound;

import org.apache.commons.math3.stat.StatUtils;

import java.util.*;
import java.util.regex.Pattern;

/**
 * 地磅算法 相关计算类
 *
 * @author dehuisun
 */
public class CalculUtils {

    /**
     * 取list平均值
     *
     * @param list
     * @return
     */
    public static List<Integer> getAverageList(List<Integer> list) {
        Integer total = 0;
        Integer threshold = 200;
        if (list != null && list.size() > 3) {
            for (int i = 0; i < list.size(); i++) {
                total += list.get(i);
            }
            int avg = total / list.size();

            for (int i = 0; i < list.size(); i++) {
                Integer num = list.get(i);
                if (Math.abs(num - avg) > threshold) {
                    list.remove(i);
                    break;
                }
            }
        }
        return list;
    }

    /**
     * 取list最大值
     *
     * @param list
     * @return
     */
    public static Integer getMax(List<Integer> list) {
        return Collections.max(list);
    }

    /**
     * 统计每个数据出现频率
     *
     * @param list
     * @return
     */
    public static Map<Integer, Integer> getfrequency(List<Integer> list) {
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (Integer temp : list) {
            Integer count = map.get(temp);
            map.put(temp, (count == null) ? 1 : count + 1);
        }
        return map;
    }

    /**
     * 检验map是否存在出现num次的数据
     *
     * @param map
     * @param num 出现次数
     * @return
     */
    public static Boolean checkMaxInfo5(Map<Integer, Integer> map, int num) {
        List<Integer> list = new ArrayList<Integer>();
        for (Integer key : map.keySet()) {
            Integer value = map.get(key);
            if (value >= num) {
                list.add(key);
            }
        }
        if (list != null && list.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取map出现num 次以上最大的数据
     *
     * @param map 数据
     * @param num 出现次数
     * @return
     */
    public static Integer getMaxInfo5(Map<Integer, Integer> map, int num) {
        List<Integer> list = new ArrayList<Integer>();
        for (Integer key : map.keySet()) {
            Integer value = map.get(key);
            if (value >= num) {
                list.add(key);
            }
        }
        return getMax(list);
    }

    /**
     * 获取出现map2次以上最大的数据
     *
     * @param map(车辆不稳有时候3次取不到)
     * @return
     */
    public static Integer getMaxInfo(Map<Integer, Integer> map) {
        List<Integer> list = new ArrayList<Integer>();
        for (Integer key : map.keySet()) {
            Integer value = map.get(key);
            if (value > 1) {
                list.add(key);
            }
//		    System.out.println("key="+key+"and value=" +map.get(key));
        }
        return getMax(list);
    }

    /**
     * 根据数组拆分组合数,并对比是否包含目标数
     *
     * @param kill 组合数
     * @param done 目标数
     * @param keys 拆分数组
     * @return
     */
    public static Boolean checkArr(Integer kill, Integer done, Integer[] keys) {
        // Integer[] keys = { 1, 2, 4, 40 };
        int n = keys.length;
        int nbit = 1 << n;
        Integer in;
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < nbit; i++) {
            in = 0;
            list.clear();
            for (int j = 0; j < n; j++) {
                int tmp = 1 << j; // 由0到n右移位
                if ((tmp & i) != 0) { // 与运算，同为1时才会是1
                    in += keys[j];
                    list.add(keys[j]);
                }
            }
            if (in == kill) {
                break;
            }
        }
        return list.contains(done) ? true : false;
    }

    /*
     * 判断是否为整数
     *
     * @param str 传入的字符串
     *
     * @return 是整数返回true,否则返回false
     */
    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 求众数[如果有多个求其中最大的]
     *
     * @param list List集合
     * @return 最大的众数
     */
    public static Integer mode(List<Integer> list) {
        double[] numbers = new double[list.size()];
        for (int i = 0; i < list.size(); i++) {
            numbers[i] = list.get(i).doubleValue();
        }
        double[] mode = StatUtils.mode(numbers);
        return Double.valueOf(StatUtils.max(mode)).intValue();
    }
}
